home *** CD-ROM | disk | FTP | other *** search
- include hobbes.inc
- include extrn.inc
-
- .DATA
-
- ; Plane masks for clipping left and right edges of rectangle
- LeftClipPlaneMask db 00fh,00eh,00ch,008h
- RightClipPlaneMask db 00fh,001h,003h,007h
-
-
- .CODE
-
-
- ;----------------------------------------------------------------------------
- ; void RectangleFillAligned(int x0, int y0, int x1, int y1, COLOR);
- ;
- public _RectangleFillAligned
- _RectangleFillAligned proc
- ARG X0, Y0, X1, Y1, COLOR
- push bp
- mov bp,sp
- push ds
- mov ax,@data
- mov ds,ax
-
- mov es,_ModeX_Segment ; point ES:DI to the first rectangle pixel's address
- push si
- push di
-
- mov dx,SC_INDEX ; set the Sequence Controller Index to
- mov al,MAP_MASK ; point to the Map Mask register
- out dx,al
- inc dx ; point DX to the SC Data register
- mov al,0fh ; write to all planes
- out dx,al ; set the mask
-
- cld
- mov di,Y0
- shl di,1 ; address of the row offset word
- mov di,word ptr _RowOffset[di]
- mov ax,X0
- shr ax,2 ; X/4 = offset of pixel in scan line
- add di,ax ; final offset of pixel in page
-
- mov cx,X1 ; calculate # of addresses across rect
- mov bx,X0
- and bx,not 011b
- sub cx,bx
- shr cx,2 ; # of addresses across box to fill - 1
- inc cx ; # of addresses across box to fill
- mov si,cx ; save a copy in SI
- mov bx,Y1
- sub bx,Y0 ; BX = height of rectangle - 1
- mov al,byte ptr COLOR ; color with which to fill
- mov ah,al
- mov bp,_Virtual_Width_Addr ; stack frame isn't needed any more
- sub bp,cx ; distance from end of one scan line to start of next
- @@BoxAligned_RowsLoop:
- shr cx,1 ; get the number of pixel pairs
- rep stosw ; draw the middle addresses eight pixels apiece
- adc cx,0 ; odd number of pixels?
- rep stosb ; rep used to draw the last pixel ONLY if necessary
- add di,bp ; point to the start of the next scan line of
- ; the rectangle
- mov cx,si ; retrieve width in addresses
- dec bx ; count down scan lines
- jnl @@BoxAligned_RowsLoop
- @@BoxAligned_Done:
- pop di
- pop si
- pop ds
- pop bp
- ret
- _RectangleFillAligned endp
-
-
-
-
- ;----------------------------------------------------------------------------
- ; void RectangleFill(int StartX, int StartY, int EndX, int EndY, COLOR);
-
- public _RectangleFill
- _RectangleFill proc far
- ARG StartX:WORD, StartY:WORD, EndX:WORD, EndY:WORD, Color:WORD
- push bp
- mov bp,sp
- push si
- push di
- push ds
- mov ax,@data
- mov ds,ax
-
- cld
- mov ax,_Virtual_Width_Addr
- mul StartY ;offset in page of top rectangle scan line
- mov di,StartX
- shr di,1 ;X/4 = offset of first rectangle pixel in scan
- shr di,1 ; line
- add di,ax ;offset of first rectangle pixel in page
- add di,_Display_Offset ;offset of first rectangle pixel in
- ; display memory
- mov ax,_ModeX_Segment ;point ES:DI to the first rectangle
- mov es,ax ; pixel's address
- mov dx,SC_INDEX ;set the Sequence Controller Index to
- mov al,MAP_MASK ; point to the Map Mask register
- out dx,al
- inc dx ;point DX to the SC Data register
- mov si,StartX
- and si,0003h ;look up left edge plane mask
- mov bh,LeftClipPlaneMask[si] ; to clip & put in BH
- mov si,EndX
- and si,0003h ;look up right edge plane
- mov bl,RightClipPlaneMask[si] ; mask to clip & put in BL
-
- mov cx,EndX ;calculate # of addresses across rect
- mov si,StartX
- cmp cx,si
- jle @@FillDone ;skip if 0 or negative width
- dec cx
- and si,not 011b
- sub cx,si
- shr cx,1
- shr cx,1 ;# of addresses across rectangle to fill - 1
- jnz @@MasksSet ;there's more than one byte to draw
- and bh,bl ;there's only one byte, so combine the left
- ; and right edge clip masks
- @@MasksSet:
- mov si,EndY
- sub si,StartY ;BX = height of rectangle
- jle @@FillDone ;skip if 0 or negative height
- mov ah,byte ptr Color ;color with which to fill
- mov bp,_Virtual_Width_Addr ;stack frame isn't needed any more
- sub bp,cx ;distance from end of one scan line to start
- dec bp ; of next
- @@FillRowsLoop:
- push cx ;remember width in addresses - 1
- mov al,bh ;put left-edge clip mask in AL
- out dx,al ;set the left-edge plane (clip) mask
- mov al,ah ;put color in AL
- stosb ;draw the left edge
- dec cx ;count off left edge byte
- js @@FillLoopBottom ;that's the only byte
- jz @@DoRightEdge ;there are only two bytes
- mov al,00fh ;middle addresses are drawn 4 pixels at a pop
- out dx,al ;set the middle pixel mask to no clip
- mov al,ah ;put color in AL
- rep stosb ;draw the middle addresses four pixels apiece
- @@DoRightEdge:
- mov al,bl ;put right-edge clip mask in AL
- out dx,al ;set the right-edge plane (clip) mask
- mov al,ah ;put color in AL
- stosb ;draw the right edge
- @@FillLoopBottom:
- add di,bp ;point to the start of the next scan line of
- ; the rectangle
- pop cx ;retrieve width in addresses - 1
- dec si ;count down scan lines
- jnz @@FillRowsLoop
- @@FillDone:
-
- pop ds
- pop di
- pop si
- pop bp
- ret
- _RectangleFill endp
-
-
-
-
- ;----------------------------------------------------------------------------
- ; void RectangleFillClip(int StartX, int StartY, int EndX, int EndY, COLOR);
-
- public _RectangleFillClip
- _RectangleFillClip proc far
- ARG StartX:WORD, StartY:WORD, EndX:WORD, EndY:WORD, Color:WORD
- push bp
- mov bp,sp
- push si
- push di
- push ds
- mov ax,@data
- mov ds,ax
-
- ; clip it
- ; yeah, it's may be kinda cheezy, but it's still fairly quick
- ; (plus, it took about 5min :-])
- @@_ClipLeft:
- mov ax, StartX
- cmp ax, _ClipLeft
- jg @@_ClipRight
- mov ax, _ClipLeft
- mov StartX,ax
- @@_ClipRight:
- mov ax, EndX
- cmp ax, _ClipRight
- jle @@_ClipTop
- mov ax, _ClipRight
- mov EndX, ax
- @@_ClipTop:
- mov ax, StartY
- cmp ax, _ClipTop
- jg @@_ClipBottom
- mov ax, _ClipTop
- mov StartY, ax
- @@_ClipBottom:
- mov ax, EndY
- cmp ax, _ClipBottom
- jle @@ClipDone
- mov ax, _ClipBottom
- mov EndY, ax
-
- @@ClipDone:
- cld
- mov di,StartY
- shl di,1
- mov ax,word ptr _RowOffset[di]
- mov di,StartX
- shr di,1 ;X/4 = offset of first rectangle pixel in scan
- shr di,1 ; line
- add di,ax ;offset of first rectangle pixel in page
- add di,_Display_Offset ;offset of first rectangle pixel in
- ; display memory
- mov ax,_ModeX_Segment ;point ES:DI to the first rectangle
- mov es,ax ; pixel's address
- mov dx,SC_INDEX ;set the Sequence Controller Index to
- mov al,MAP_MASK ; point to the Map Mask register
- out dx,al
- inc dx ;point DX to the SC Data register
- mov si,StartX
- and si,0003h ;look up left edge plane mask
- mov bh,LeftClipPlaneMask[si] ; to clip & put in BH
- mov si,EndX
- and si,0003h ;look up right edge plane
- mov bl,RightClipPlaneMask[si] ; mask to clip & put in BL
-
- mov cx,EndX ;calculate # of addresses across rect
- mov si,StartX
- cmp cx,si
- jle @@FillDone ;skip if 0 or negative width
- dec cx
- and si,not 011b
- sub cx,si
- shr cx,1
- shr cx,1 ;# of addresses across rectangle to fill - 1
- jnz @@MasksSet ;there's more than one byte to draw
- and bh,bl ;there's only one byte, so combine the left
- ; and right edge clip masks
- @@MasksSet:
- mov si,EndY
- sub si,StartY ;BX = height of rectangle
- jle @@FillDone ;skip if 0 or negative height
- mov ah,byte ptr Color ;color with which to fill
- mov bp,_Virtual_Width_Addr ;stack frame isn't needed any more
- sub bp,cx ;distance from end of one scan line to start
- dec bp ; of next
- @@FillRowsLoop:
- push cx ;remember width in addresses - 1
- mov al,bh ;put left-edge clip mask in AL
- out dx,al ;set the left-edge plane (clip) mask
- mov al,ah ;put color in AL
- stosb ;draw the left edge
- dec cx ;count off left edge byte
- js @@FillLoopBottom ;that's the only byte
- jz @@DoRightEdge ;there are only two bytes
- mov al,00fh ;middle addresses are drawn 4 pixels at a pop
- out dx,al ;set the middle pixel mask to no clip
- mov al,ah ;put color in AL
- rep stosb ;draw the middle addresses four pixels apiece
- @@DoRightEdge:
- mov al,bl ;put right-edge clip mask in AL
- out dx,al ;set the right-edge plane (clip) mask
- mov al,ah ;put color in AL
- stosb ;draw the right edge
- @@FillLoopBottom:
- add di,bp ;point to the start of the next scan line of
- ; the rectangle
- pop cx ;retrieve width in addresses - 1
- dec si ;count down scan lines
- jnz @@FillRowsLoop
- @@FillDone:
- pop ds
- pop di
- pop si
- pop bp
- ret
- _RectangleFillClip endp
-
-
-
-
-
-
- ;----------------------------------------------------------------------------
- ; void RectangleFillPattern(int StartX, int StartY, int EndX, int EndY, PATTERN);
-
- public _RectangleFillPattern
- _RectangleFillPattern proc far
- ARG StartX:WORD, StartY:WORD, EndX:WORD, EndY:WORD, Pattern:DWORD
- LOCAL NextScanOffset:WORD, RectAddrWidth:WORD, Height:WORD = LocalStack
- push bp
- mov bp,sp
- sub sp,LocalStack
- push si
- push di
- push ds
-
-
- cld
- mov ax,_ModeX_Segment ;point ES to display memory
- mov es,ax
- ;copy pattern to display memory buffer
- ; mov si,Pattern ;point to pattern to fill with
- mov di,_Pattern_Offset ;point ES:DI to pattern buffer
- lds si,Pattern
- mov dx,SC_INDEX ;point Sequence Controller Index to
- mov al,MAP_MASK ; Map Mask
- out dx,al
- inc dx ;point to SC Data register
- mov cx,4 ;4 pixel quadruplets in pattern
- @@DownloadPatternLoop:
- mov al,1 ;
- out dx,al ;select plane 0 for writes
- movsb ;copy over next plane 0 pattern pixel
- dec di ;stay at same address for next plane
- mov al,2 ;
- out dx,al ;select plane 1 for writes
- movsb ;copy over next plane 1 pattern pixel
- dec di ;stay at same address for next plane
- mov al,4 ;
- out dx,al ;select plane 2 for writes
- movsb ;copy over next plane 2 pattern pixel
- dec di ;stay at same address for next plane
- mov al,8 ;
- out dx,al ;select plane 3 for writes
- movsb ;copy over next plane 3 pattern pixel
- ; and advance address
- loop @@DownloadPatternLoop
-
- mov ax, @data
- mov ds,ax
-
- mov dx,GC_INDEX ;set the bit mask to select all bits
- mov ax,00000h+BIT_MASK ; from the latches and none from
- out dx,ax ; the CPU, so that we can write the
- ; latch contents directly to memory
- mov ax,StartY ;top rectangle scan line
- mov si,ax
- and si,011b ;top rect scan line modulo 4
- add si,_Pattern_Offset ;point to pattern scan line that
- ; maps to top line of rect to draw
- mov dx,_Virtual_Width_Addr
- mul dx ;offset in page of top rectangle scan line
-
- mov di,StartX
- mov bx,di
- shr di,1 ;X/4 = offset of first rectangle pixel in scan
- shr di,1 ; line
- add di,ax ;offset of first rectangle pixel in page
- add di,_Display_Offset ;offset of first rectangle pixel in
- ; display memory
- and bx,0003h ;look up left edge plane mask
- mov ah,LeftClipPlaneMask[bx] ; to clip
- mov bx,EndX
- and bx,0003h ;look up right edge plane
- mov al,RightClipPlaneMask[bx] ; mask to clip
- mov bx,ax ;put the masks in BX
-
- mov cx,EndX ;calculate # of addresses across rect
- mov ax,StartX
- cmp cx,ax
- jle @@FillDone ;skip if 0 or negative width
- dec cx
- and ax,not 011b
- sub cx,ax
- shr cx,1
- shr cx,1 ;# of addresses across rectangle to fill - 1
- jnz @@MasksSet ;there's more than one pixel to draw
- and bh,bl ;there's only one pixel, so combine the left
- ; and right edge clip masks
- @@MasksSet:
- mov ax,EndY
- sub ax,StartY ;AX = height of rectangle
- jle @@FillDone ;skip if 0 or negative height
- mov Height,ax
- mov ax,_Virtual_Width_Addr
- sub ax,cx ;distance from end of one scan line to start
- dec ax ; of next
- mov NextScanOffset,ax
- mov RectAddrWidth,cx ;remember width in addresses - 1
- mov dx,SC_INDEX+1 ;point to Sequence Controller Data reg
- ; (SC Index still points to Map Mask)
- @@FillRowsLoop:
- mov cx,RectAddrWidth ;width across - 1
- mov al,es:[si] ;read display memory to latch this scan
- ; line's pattern
- inc si ;point to the next pattern scan line, wrapping
- jnz short @@NoWrap ; back to the start of the pattern if
- sub si,4 ; we've run off the end
- @@NoWrap:
- mov al,bh ;put left-edge clip mask in AL
- out dx,al ;set the left-edge plane (clip) mask
- stosb ;draw the left edge (pixels come from latches;
- ; value written by CPU doesn't matter)
- dec cx ;count off left edge address
- js @@FillLoopBottom ;that's the only address
- jz @@DoRightEdge ;there are only two addresses
- mov al,00fh ;middle addresses are drawn 4 pixels at a pop
- out dx,al ;set the middle pixel mask to no clip
- rep stosb ;draw the middle addresses four pixels apiece
- ; (from latches; value written doesn't matter)
- @@DoRightEdge:
- mov al,bl ;put right-edge clip mask in AL
- out dx,al ;set the right-edge plane (clip) mask
- stosb ;draw the right edge (from latches; value
- ; written doesn't matter)
- @@FillLoopBottom:
- add di,NextScanOffset ;point to the start of the next scan
- ; line of the rectangle
- dec word ptr Height ;count down scan lines
- jnz @@FillRowsLoop
- @@FillDone:
- mov dx,GC_INDEX+1 ;restore the bit mask to its default,
- mov al,0ffh ; which selects all bits from the CPU
- out dx,al ; and none from the latches (the GC
- ; Index still points to Bit Mask)
-
- pop ds
- pop di
- pop si
- mov sp,bp
- pop bp
- ret
- _RectangleFillPattern endp
-
-
-
-
-
- ;----------------------------------------------------------------------------
- ; void RectangleFillPatternClip(int StartX, int StartY, int EndX, int EndY, PATTERN);
-
- public _RectangleFillPatternClip
- _RectangleFillPatternClip proc far
- ARG StartX:WORD, StartY:WORD, EndX:WORD, EndY:WORD, Pattern:DWORD
- LOCAL NextScanOffset:WORD, RectAddrWidth:WORD, Height:WORD = LocalStack
- push bp
- mov bp,sp
- sub sp,LocalStack
- push si
- push di
- push ds
-
-
- ; clip it
- ; yeah, it's may be kinda cheezy, but it's still fairly quick
- ; (plus, it took about 5min :-])
- @@_ClipLeft:
- mov ax, StartX
- cmp ax, _ClipLeft
- jg @@_ClipRight
- mov ax, _ClipLeft
- mov StartX,ax
- @@_ClipRight:
- mov ax, EndX
- cmp ax, _ClipRight
- jle @@_ClipTop
- mov ax, _ClipRight
- mov EndX, ax
- @@_ClipTop:
- mov ax, StartY
- cmp ax, _ClipTop
- jg @@_ClipBottom
- mov ax, _ClipTop
- mov StartY, ax
- @@_ClipBottom:
- mov ax, EndY
- cmp ax, _ClipBottom
- jle @@ClipDone
- mov ax, _ClipBottom
- mov EndY, ax
-
- @@ClipDone:
- cld
- mov ax,_ModeX_Segment ;point ES to display memory
- mov es,ax
- ;copy pattern to display memory buffer
- ; mov si,Pattern ;point to pattern to fill with
- mov di,_Pattern_Offset ;point ES:DI to pattern buffer
- lds si,Pattern
- mov dx,SC_INDEX ;point Sequence Controller Index to
- mov al,MAP_MASK ; Map Mask
- out dx,al
- inc dx ;point to SC Data register
- mov cx,4 ;4 pixel quadruplets in pattern
- @@DownloadPatternLoop:
- mov al,1 ;
- out dx,al ;select plane 0 for writes
- movsb ;copy over next plane 0 pattern pixel
- dec di ;stay at same address for next plane
- mov al,2 ;
- out dx,al ;select plane 1 for writes
- movsb ;copy over next plane 1 pattern pixel
- dec di ;stay at same address for next plane
- mov al,4 ;
- out dx,al ;select plane 2 for writes
- movsb ;copy over next plane 2 pattern pixel
- dec di ;stay at same address for next plane
- mov al,8 ;
- out dx,al ;select plane 3 for writes
- movsb ;copy over next plane 3 pattern pixel
- ; and advance address
- loop @@DownloadPatternLoop
-
- mov ax, @data
- mov ds,ax
-
- mov dx,GC_INDEX ;set the bit mask to select all bits
- mov ax,00000h+BIT_MASK ; from the latches and none from
- out dx,ax ; the CPU, so that we can write the
- ; latch contents directly to memory
- mov ax,StartY ;top rectangle scan line
- mov si,ax
- and si,011b ;top rect scan line modulo 4
- add si,_Pattern_Offset ;point to pattern scan line that
- ; maps to top line of rect to draw
- mov dx,_Virtual_Width_Addr
- mul dx ;offset in page of top rectangle scan line
- mov di,StartX
- mov bx,di
- shr di,1 ;X/4 = offset of first rectangle pixel in scan
- shr di,1 ; line
- add di,ax ;offset of first rectangle pixel in page
- add di,_Display_Offset ;offset of first rectangle pixel in
- ; display memory
- and bx,0003h ;look up left edge plane mask
- mov ah,LeftClipPlaneMask[bx] ; to clip
- mov bx,EndX
- and bx,0003h ;look up right edge plane
- mov al,RightClipPlaneMask[bx] ; mask to clip
- mov bx,ax ;put the masks in BX
-
- mov cx,EndX ;calculate # of addresses across rect
- mov ax,StartX
- cmp cx,ax
- jle @@FillDone ;skip if 0 or negative width
- dec cx
- and ax,not 011b
- sub cx,ax
- shr cx,1
- shr cx,1 ;# of addresses across rectangle to fill - 1
- jnz @@MasksSet ;there's more than one pixel to draw
- and bh,bl ;there's only one pixel, so combine the left
- ; and right edge clip masks
- @@MasksSet:
- mov ax,EndY
- sub ax,StartY ;AX = height of rectangle
- jle @@FillDone ;skip if 0 or negative height
- mov Height,ax
- mov ax,_Virtual_Width_Addr
- sub ax,cx ;distance from end of one scan line to start
- dec ax ; of next
- mov NextScanOffset,ax
- mov RectAddrWidth,cx ;remember width in addresses - 1
- mov dx,SC_INDEX+1 ;point to Sequence Controller Data reg
- ; (SC Index still points to Map Mask)
- @@FillRowsLoop:
- mov cx,RectAddrWidth ;width across - 1
- mov al,es:[si] ;read display memory to latch this scan
- ; line's pattern
- inc si ;point to the next pattern scan line, wrapping
- jnz short @@NoWrap ; back to the start of the pattern if
- sub si,4 ; we've run off the end
- @@NoWrap:
- mov al,bh ;put left-edge clip mask in AL
- out dx,al ;set the left-edge plane (clip) mask
- stosb ;draw the left edge (pixels come from latches;
- ; value written by CPU doesn't matter)
- dec cx ;count off left edge address
- js @@FillLoopBottom ;that's the only address
- jz @@DoRightEdge ;there are only two addresses
- mov al,00fh ;middle addresses are drawn 4 pixels at a pop
- out dx,al ;set the middle pixel mask to no clip
- rep stosb ;draw the middle addresses four pixels apiece
- ; (from latches; value written doesn't matter)
- @@DoRightEdge:
- mov al,bl ;put right-edge clip mask in AL
- out dx,al ;set the right-edge plane (clip) mask
- stosb ;draw the right edge (from latches; value
- ; written doesn't matter)
- @@FillLoopBottom:
- add di,NextScanOffset ;point to the start of the next scan
- ; line of the rectangle
- dec word ptr Height ;count down scan lines
- jnz @@FillRowsLoop
- @@FillDone:
- mov dx,GC_INDEX+1 ;restore the bit mask to its default,
- mov al,0ffh ; which selects all bits from the CPU
- out dx,al ; and none from the latches (the GC
- ; Index still points to Bit Mask)
-
- pop ds
- pop di
- pop si
- mov sp,bp
- pop bp
- ret
- _RectangleFillPatternClip endp
-
-
- ;----------------------------------------------------------------------------
- ;void ClearClipPort() {
- ; RectangleFill(ClipLeft, ClipTop, ClipRight, ClipBottom);
- ;}
-
- public _ClearClipPort
- _ClearClipPort proc
- push ds
- mov ax,@data
- mov ds,ax
-
- xor ax,ax
- push ax ;push the color (black)
- mov ax,_ClipBottom
- push ax
- mov ax,_ClipRight
- dec ax
- push ax
- mov ax,_ClipTop
- push ax
- mov ax,_ClipLeft
- push ax
- call _RectangleFillAligned
- pop ax
- pop ax
- pop ax
- pop ax
- pop ax
- pop ds
- ret
- _ClearClipPort endp
-
-
- ;----------------------------------------------------------------------------
- ;void ClearVirtualPort() {
- ; RectangleFill(0, 0, Virtual_Width, Virtual_Height, BLACK);
- ;}
- public _ClearVirtualPort
- _ClearVirtualPort proc
- push ds
- mov ax,@data
- mov ds,ax
-
- xor ax,ax
- push ax ;push color
- mov bx,_Virtual_Height_Pix
- push bx
- mov bx,_Virtual_Width_Pix
- dec bx
- push bx
- push ax
- push ax
- call _RectangleFillAligned
- pop ax
- pop ax
- pop ax
- pop ax
- pop ax
- pop ds
- ret
- _ClearVirtualPort endp
-
-
- ;----------------------------------------------------------------------------
- END